using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.CodeDom;
using System.CodeDom.Compiler;

namespace DacTaHinhThuc
{
    public class Parser
    {
        #region fields
        private Parameter[] m_arrPara;        //mang chua cac tham so cua ham
        private Parameter m_result;           //luu ket qua tra ve cua ham
        private string m_strNameMethod;       //luu ten ham

<<<<<<< .mine
        private int m_iNum;                     //luu bai tap dang xet

        private string[] m_preCondition;          //luu phan pre
=======
        private int m_iNum;                     //luu bai tap dang xet

        private string m_preCondition;          //luu phan pre
>>>>>>> .r17
        private string[] m_postCondition;         //luu phan post la mang cac truong hop ket qua
        private string m_string;                //luu phan khai bao dau cua dac ta (gom TenHam(a,R)kq:R)
        
        private string[] m_arr = { "pre", "Pre", "post", "Post" };
<<<<<<< .mine
        private string[] listOldSymbol = { mySymbol.And, mySymbol.Or, mySymbol.NotEqual };
        private string[] listNewSymbol = { "&&", "||", "!=" };
=======
        private string[] listOldSymbol = { mySymbol.And, mySymbol.Or ,mySymbol.Not};
        private string[] listNewSymbol = { "&&", "||", "!" };
>>>>>>> .r17
        private string[] listBracket = { "(", ")" };
        private char[] listColon = { ':' };
        private char[] listComma = { ',' };

        #endregion

        #region properties
<<<<<<< .mine
        public int Num
        {
            get { return this.m_iNum; }
        }
=======
        public int Num
        {
            get { return this.m_iNum; }
        }

>>>>>>> .r17
        public Parameter[] ArrPara
        {
            get { return this.m_arrPara; }
            set { this.m_arrPara = value; }
        }
        public Parameter Result
        {
            get { return this.m_result; }
            set { this.m_result = value; }
        }
        public string NameMethod
        {
            get { return this.m_strNameMethod; }
            set { this.m_strNameMethod = value; }
        }
        public string[] PreCondition
        {
            get { return this.m_preCondition; }
            set { this.m_preCondition = value; }
        }
        public string[] PostCondition
        {
            get { return this.m_postCondition; }
            set { this.m_postCondition = value; }
        }
        
        #endregion

        #region methods
        public Parser()
        {
            this.m_result = new Parameter();
        }
      
        /// <summary>
        /// ham doc tu rich text box
        /// </summary>
<<<<<<< .mine
        /// <param name="s">du lieu dac ta</param>
        public void Input(string s)
        {            
            string[] arr = s.Split(this.m_arr, StringSplitOptions.None);
=======
        /// <param name="s">du lieu dac ta</param>
        public void Input(string s)
        {
            
            string[] arr = s.Split(this.m_arr, StringSplitOptions.None);
>>>>>>> .r17
            if (arr.Length != 3)
            {                
                throw new Exception("Cau truc ham dac ta khong chinh xac!");
            }
            else
            {
                //kiem tra xem dau ngoac co hop le hay khong?
                if (Checking.CheckBraket(arr[0]))
                {
                    this.m_string = arr[0];

                    try
                    {
<<<<<<< .mine
                        if (arr[2].Contains(mySymbol.Exist) || arr[2].Contains(mySymbol.All) || arr[2].Contains("*"))
                        {
                            //xu ly cho bai so 2 :D
                            this.m_iNum = 2;
                            //xu ly o day
                        }
                        else
                        {
                            //xu ly cho bai so 1
                            this.m_iNum = 1;
                        }

                        //parse de lay ten ham, tham so ...
                        this.Parse();

=======
                        if (arr[2].Contains(mySymbol.Exist) || arr[2].Contains(mySymbol.All))
                        {
                            //xu ly cho bai so 2 :D
                            this.m_iNum = 2;
                            //xu ly o day


                        }
                        else
                        {
                            //xu ly cho bai so 1
                            this.m_iNum = 1;                            
                        }

                        //parse de lay ten ham, tham so ...
                        this.Parse();

>>>>>>> .r17
                        //xu ly pre condition
                        this.m_preCondition = this.ParsePreCondition(arr[1]);

                        //xy ly post condition
                        this.m_postCondition = this.ParsePostCondition(arr[2]);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(ex.Message);
                    }
                }
                else
<<<<<<< .mine
                {                   
                    throw new Exception("Sai dau ngoac!");
=======
                {                   
                    throw new Exception("Sai dau ngoac!");

>>>>>>> .r17
                }
            }
        }

        
        /// <summary>
        /// ham de doi dieu kien pre condition. vd: (a>b)/\(c>d) => (a>b)&&(c>d)
        /// </summary>
        /// <returns></returns>
<<<<<<< .mine
        public string[] ParsePreCondition(string s)
=======
        public string ParsePreCondition(string s)
>>>>>>> .r17
        {
<<<<<<< .mine
            if (Checking.CheckBraket(s))
=======
            int i;
            s = s.Trim();
            for (i = 0; i < listOldSymbol.Length; i++)
>>>>>>> .r17
            {
                int i;
                s = s.Trim();
                s = s.Replace(mySymbol.NotEqual, "!=");
                s = s.Replace("(", "");
                s = s.Replace(")", "");

                for (i = 0; i < s.Length; i++)
                {
                    if (s[i] == '=' && s[i - 1] != '>' && s[i - 1] != '<' && s[i - 1] != '!')
                    {
                        s = s.Insert(i, "=");
                        i++;
                    }
                }

                //chia ra cac dieu kien cua pre
                string[] arr = s.Split(new string[] { mySymbol.Or }, StringSplitOptions.RemoveEmptyEntries);

                //xu ly cho bai 2, thay nhung chi so mang [] -> ()
                if (this.m_iNum == 2)
                {

                }

                return arr;
            }
<<<<<<< .mine
            else
                throw new Exception("Dau ngoac cua pre condition khong hop le!");
=======

            for (i = 0; i < s.Length; i++)
            {
                if (s[i] == '=' && s[i - 1] != '>' && s[i - 1] != '<')
                {
                    s = s.Insert(i, "=");
                    i++;
                }
            }

            return s;
>>>>>>> .r17
        }

        /// <summary>
        /// ham de tra ve danh sach cac cau lenh
        /// </summary>
        /// <returns></returns>
        public string[] ParsePostCondition(string s)
        {
<<<<<<< .mine
            if (Checking.CheckBraket(s))
            {
                s = s.Replace(mySymbol.NotEqual, "!=");

                if (this.m_iNum == 1)
                {
                    s = s.Trim();
                    s = s.Replace("(", "");
                    s = s.Replace(")", "");

                    //chia ra nhieu truong hop ket qua
                    string[] s1 = { mySymbol.Or };
                    string[] arr = s.Split(s1, StringSplitOptions.RemoveEmptyEntries);

                    return arr;
                }
                else
                {
                    //bai 2 parse ra o day
                    List<string> list = new List<string>();

                    s = s.Trim();
                    if (s == "")
                    {
                        return list.ToArray();
                    }
                    s = s.Substring(this.m_result.Name.Length + 1, s.Length - this.m_result.Name.Length - 1);

                    //tach ra nhieu khuc, moi khuc gom TT va VM dung truoc
                    int i;
                    int index = 0;


                    for (i = 1; i < s.Length; i++)
                    {
                        if (s[i] == '.' && (s[i - 1] == '}' || s[i - 1] == ')' || s[i - 1] == ']'))
                        {
                            string tmp = s.Substring(index, i);
                            s = s.Substring(i + 1);
                            list.Add(tmp);
                            i = 1;
                        }
                    }
                    list.Add(s);

                    for (i = 0; i < list.Count; i++)
                    {
                        list[i] = list[i].Replace("(", "");
                        list[i] = list[i].Replace(")", "");
                    }
                    return list.ToArray();
                }
            }
            else
                throw new Exception("Dau ngoac cua post condition khong hop le!");
=======
            if (this.m_iNum == 1)
            {
                s = s.Trim();
                //chia ra nhieu truong hop ket qua
                string[] s1 = { mySymbol.Or };
                string[] arr = s.Split(s1, StringSplitOptions.RemoveEmptyEntries);
               
                return arr;
            }
            else
            {
                //bai 2 parse ra o day
                s = s.Trim();
                //chia ra nhieu truong hop ket qua
                string[] s1 = { mySymbol.Or };
                string[] arr = s.Split(s1, StringSplitOptions.RemoveEmptyEntries);

                return arr;
            }
>>>>>>> .r17
        }
        
        private void Parse()
<<<<<<< .mine
        {            
            string[] tmp = this.m_string.Split(listBracket, StringSplitOptions.None);
=======
        {
            string[] tmp = this.m_string.Split(listBracket, StringSplitOptions.None);
>>>>>>> .r17
            if (tmp.Length == 3)
            {
                try
                {
                    AddNameProc(tmp[0]);
                    AddPara(tmp[1]);
                    AddResult(tmp[2]);
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }
            else
            {
                throw new Exception("Sai cau truc!");
            }
        }
        private void AddNameProc(string name)
        {
            this.m_strNameMethod = name.Trim();
        }
        
        private void AddPara(string lPara)
        {
            lPara = lPara.Trim();
            string[] groupPara = lPara.Split(listComma, StringSplitOptions.RemoveEmptyEntries);

            this.m_arrPara = new Parameter[groupPara.Length];

            int i;
            string[] tmp;
            for (i = 0; i < groupPara.Length; i++)
            {
                this.m_arrPara[i] = new Parameter();
                tmp = groupPara[i].Split(listColon, StringSplitOptions.RemoveEmptyEntries);
                if (tmp.Length != 2)
                {
                    throw new Exception("Tham so thu " + i.ToString() + " khong chinh xac!");
                    
                }
                this.m_arrPara[i].Name = tmp[0].Trim();

                string str;
                tmp[1] = tmp[1].Trim();
                if (tmp[1][tmp[1].Length - 1] == '*')
                {
                    this.m_arrPara[i].IsArr = true;
                    tmp[1] = tmp[1].Substring(0, tmp[1].Length - 1);
                }
                else
                {
                    if (tmp[1].Contains("-set"))
                    {
                        this.m_arrPara[i].IsSet = true;
                        tmp[1] = tmp[1].Substring(0, tmp[1].Length - "-set".Length);
                    }
                    else
                    {

                    }
                }
                str = Mapping.MappingSetToType(tmp[1].Trim());
                if (str == null)
                {
                    throw new Exception("Kieu du lieu cua tham so thu " + i.ToString() + " khong chinh xac");
                    
                }


                this.m_arrPara[i].Type = str;
                this.m_arrPara[i].Set = tmp[1].Trim();

                str = Mapping.MappingSetToSystemType(tmp[1].Trim());
                if (str == null)
                {
                    throw new Exception("Kieu du lieu cua tham so thu " + i.ToString() + " khong chinh xac");
                }
                this.m_arrPara[i].SystemType = str;
            }
            
            //kiem tra xem co tham so trung ten hay khong
            int index = Checking.CheckSameParameter(this.m_arrPara);
            if (index != -1)
            {
                throw new Exception("Tham so thu " + index.ToString() + " bi trung ten");
                
            }
<<<<<<< .mine
            
=======

            
>>>>>>> .r17
            //kiem tra xem dat ten tham so co hop le hay khong
            index = Checking.CheckNameParameter(this.m_arrPara);
            if (index != -1)
            {
                throw new Exception("Ten tham so thu " + index.ToString() + " dat khong hop le");
               
            }
            

            //kiem tra ten ham
            if (!Checking.CheckNameFunction(this.m_strNameMethod))
            {
                throw new Exception("Ten ham dat sai");
                
            }
             
        }

        private void AddResult(string result)
        {
            string[] tmp;
            result = result.Trim();
            tmp = result.Split(listColon, StringSplitOptions.RemoveEmptyEntries);
            if (tmp.Length == 2)
            {
                this.m_result = new Parameter();

                this.m_result.Name = tmp[0].Trim();

                string str;
                str = Mapping.MappingSetToType(tmp[1].Trim());
                if (str == null)
                {
                    throw new Exception("Khong tim thay kieu du lieu cho ket qua");
                }

                this.m_result.Type = str;
                this.m_result.Set = tmp[1].Trim();

                str = Mapping.MappingSetToSystemType(tmp[1].Trim());
                if (str == null)
                {
                    throw new Exception("Khong tim thay kieu du lieu cho ket qua");
                }
                this.m_result.SystemType = str;

                //kiem tra ten tham so ket qua
                if (!Checking.CheckNameFunction(this.m_result.Name))
                {
                    throw new Exception("Ten ket qua tra ve dat sai");
                }

            }
            else
            {
                throw new Exception("Gia tri tra ve bi sai cau truc");
            }
        }              
        #endregion
    }
}
